package com.cl.it.spider;

import com.cl.it.mbg.entity.Company;
import com.cl.it.mbg.service.ICompanyService;
import com.cl.it.mbg.service.INewsService;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.openqa.selenium.*;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;

@Slf4j
public abstract class AbstractSpider {

    @Value("${selenium.driver.chrome}")
    protected String chomeDriver;

    @Autowired
    protected ICompanyService companyService;

    @Autowired
    protected INewsService newsService;

    public void execute() {
        SeleniumSpider spider = new SeleniumSpider(chomeDriver);
        try {
            login(spider.getDriver(), spider.getWait());
            List<Company> companies = companyService.list();
            for (Company company : companies) {
                executeSingleCompany(spider.getDriver(), spider.getWait(), company);
                sleep(2000L);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            spider.getDriver().quit();
        }
    }

    protected abstract void executeSingleCompany(WebDriver driver, WebDriverWait wait, Company company);

    protected abstract void login(WebDriver driver, WebDriverWait wait);

    protected void sleep(long mill) {
        try {
            Thread.sleep(mill);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public boolean has(SearchContext driver, String css) {
        try {
            List<WebElement> elements = driver.findElements(By.cssSelector(css));
            return (elements == null || elements.size() == 0) ? false : true;
        } catch (NoSuchElementException e) {
            return false;
        }
    }

    public boolean has(SearchContext driver, By by) {
        try {
            List<WebElement> elements = driver.findElements(by);
            return (elements == null || elements.size() == 0) ? false : true;
        } catch (NoSuchElementException e) {
            return false;
        }
    }

    protected String href(SearchContext driver, String cssSelector) {
        WebElement a = selector(driver, cssSelector);
        if (a == null) {
            return "";
        }
        return a.getAttribute("href");
    }

    protected String href(SearchContext driver, By by) {
        WebElement a = selector(driver, by);
        if (a == null) {
            return "";
        }
        return a.getAttribute("href");
    }

    protected WebElement selector(SearchContext driver, String cssSelector) {
        if (!has(driver, By.cssSelector(cssSelector))) {
            return null;
        }
        return driver.findElement(By.cssSelector(cssSelector));
    }

    protected WebElement selector(SearchContext driver, By by) {
        if (!has(driver, by)) {
            return null;
        }
        return driver.findElement(by);
    }

    protected List<WebElement> selectors(SearchContext driver, String cssSelector) {
        if (!has(driver, By.cssSelector(cssSelector))) {
            return null;
        }
        return driver.findElements(By.cssSelector(cssSelector));
    }

    protected List<WebElement> selectors(SearchContext driver, By by) {
        if (!has(driver, by)) {
            return null;
        }
        return driver.findElements(by);
    }

    protected String selectorText(SearchContext driver, String cssSelector) {
        if (!has(driver, By.cssSelector(cssSelector))) {
            return null;
        }
        return driver.findElement(By.cssSelector(cssSelector)).getText().trim();
    }

    protected String selectorText(SearchContext driver, By by) {
        if (!has(driver, by)) {
            return null;
        }
        return driver.findElement(by).getText().trim();
    }

    protected String selectorHtml(SearchContext driver, String cssSelector) {
        if (!has(driver, By.cssSelector(cssSelector))) {
            return null;
        }
        return driver.findElement(By.cssSelector(cssSelector)).getAttribute("innerHTML");
    }

    protected String selectorHtml(SearchContext driver, By by) {
        if (!has(driver, by)) {
            return null;
        }
        return driver.findElement(by).getAttribute("innerHTML");
    }

    protected List<String> texts(List<WebElement> elements) {
        if (CollectionUtils.isEmpty(elements)) {
            return null;
        }
        List<String> ls = new ArrayList<>();
        for (WebElement element : elements) {
            ls.add(element.getText().trim());
        }
        return ls;
    }

    public void jsClick(WebDriver driver, String cssSelector) {
        if (!has(driver, By.cssSelector(cssSelector))) {
            return;
        }
        jsClick(driver, selector(driver, cssSelector));
    }
    public void jsClick(WebDriver driver, WebElement element) {
        executeScript(driver, "arguments[0].click();", Lists.newArrayList(element));
    }

    public Object executeScript(WebDriver driver, String script) {
        return executeScript(driver, script, null);
    }

    public Object executeScript(WebDriver driver, String script, List<Object> arguments) {
        JavascriptExecutor executor = null;
        try {
            executor = (JavascriptExecutor) driver;
        } catch (Throwable e) {
            throw new RuntimeException("该驱动不支持执行js");
        }
        Object[] argumentsArray = new Object[arguments.size()];
        for (int i = 0; i < arguments.size(); i++) {
            argumentsArray[i] = arguments.get(i);
        }
        return executor.executeScript(script, argumentsArray);
    }

}
